package Joueur;

import java.awt.Point;
import java.io.IOException;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;

import org.eclipse.jetty.websocket.WebSocket.Connection;

import Game.TableValeurs;
import Unite.Legion;

public class Player extends Observable implements Observer {
	private int _id;
	private Connection _connection;
	private Vector<Legion> _allLegions;
	private Vector<Legion> _legionsToRemove;
	private int _party;
	private int _currentActionPoint;
	private int _initialAP;

	private static int _idPlayer = 0;

	/**
	 * @param connection
	 * @param party
	 * @param legions
	 * @param actionPoint
	 */
	public Player(Connection connection, int party, Vector<Legion> legions,
			int actionPoint) {
		setId(_idPlayer);
		setConnection(connection);
		setParty(party);
		setAllLegions(legions);
		_legionsToRemove = new Vector<Legion>();
		_idPlayer++;
		_initialAP = actionPoint;
		setCurrentActionPoint(actionPoint);
	}

	/**
	 * @param party
	 */
	public void setParty(int party) {
		_party = party;
	}

	/**
	 * @return
	 */
	public int getId() {
		return _id;
	}

	/**
	 * @param id
	 */
	public void setId(int id) {
		_id = id;
	}

	/**
	 * @param connection
	 */
	public void setConnection(Connection connection) {
		_connection = connection;
	}

	/**
	 * @return les legions et leurs positions
	 */
	public String getLegionsPosition() {
		String ms = " " + _allLegions.size();
		for (Legion l : _allLegions) {
			ms += " " + l.getId() + " " + l.getX() + " " + l.getY();
		}
		ms += " ";
		return ms;
	}

	/**
	 * @param idLegion
	 * @return vrai si le player a une legion correspondant au idLegion
	 */
	public boolean hasLegion(int idLegion) {
		for (Legion l : _allLegions) {
			if (idLegion == l.getId())
				return true;
		}
		return false;
	}

	/**
	 * @return le nombre d'action point
	 */
	public void sendAP() {
		sendMessage("AP " + getCurrentActionPoint());
	}
	
	public void sendLegionInfos(int LegionId) {
		sendMessage("LI " + getLegion(LegionId).getInfos());
	}
	

	/**
	 * Envoi un message au player
	 * 
	 * @param ms
	 */
	public void sendMessage(String ms) {
		System.out.println("Message to player: " + ms);
		try {
			_connection.sendMessage(ms);
		}

		catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Place le premier joueur
	 * 
	 * @param x
	 * @param y
	 */
	public void start(int x, int y) {
		_allLegions.firstElement().setPos(x, y);
	}

	/**
	 * Permet l'action de bouger d'un player
	 * 
	 * @param tv
	 * @param tId
	 * @param lId
	 * @param x
	 * @param y
	 * @throws ActionPointException
	 */
	public void move(TableValeurs tv, int tId, int lId, int x, int y)
			throws ActionPointException {
		for (Legion l : _allLegions) {
			if (l.getId() == lId) {
				double speed = l.getSpeed(tv, tId);

				if (tv.getActionPoint("deplacement") / speed > _currentActionPoint)
					throw new ActionPointException("You can't move !");

				_currentActionPoint -= tv.getActionPoint("deplacement") / speed;

				l.setPos(x, y);
				setChanged();
				sendAP();
				notifyObservers("opponentPosition" + getLegionsPosition());
				break;
			}
		}
	}

	/**
	 * Si l'utilisateur peut combattre elle retourne vrai en plus de consommer
	 * les point pourle combat, sinon elle retourne faux
	 * 
	 * @param tv
	 * @return boolean
	 */
	public void canFight(TableValeurs tv) throws ActionPointException {
		if (tv.getActionPoint("attaque") > _currentActionPoint)
			throw new ActionPointException( "Plus de point pour combattre" );

		_currentActionPoint -= tv.getActionPoint("attaque"); 
	}

	/**
	 * @return toutes les legions du player
	 */
	public Vector<Legion> getAllLegions() {
		return _allLegions;
	}

	/**
	 * @param id
	 * @return une legion du player
	 */
	public Legion getLegion(int id) {
		Legion res = null;
		for (Legion l : _allLegions) {
			if (l.getId() == id) {
				res = l;
				break;
			}
		}
		return res;
	}

	/**
	 * @param x
	 * @param y
	 * @return la legion qui se trouve sur la prochaine tuile
	 */
	public Legion hasLegionNextTuile(int x, int y) {

		Point p = new Point(x, y);

		for (Legion leg : _allLegions) {
			if (leg.equalsPos(p))
				return leg;
		}
		return null;
	}

	/**
	 * @param allLegions
	 */
	public void setAllLegions(Vector<Legion> allLegions) {
		_allLegions = allLegions;
	}

	/**
	 * @return le party d'un player
	 */
	public int getParty() {
		return _party;
	}

	/**
	 * @param lg
	 */
	public void remove(Legion lg) {
		_allLegions.remove(lg);
	}

	/**
	 * @param lg
	 */
	public void setToRemove(Legion lg) {
		System.out.println("Legion to remove: " + lg.getId());
		_legionsToRemove.add(lg);
	}

	/**
	 * @return les legions a enlever du vector de toutes les legions
	 */
	public int removeLegions() {
		int legionsRemoved = 0;
		for (Legion lg : _legionsToRemove) {
			remove(lg);
			legionsRemoved++;
		}
		_legionsToRemove.clear();
		return legionsRemoved;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
	 */
	@Override
	public void update(Observable arg0, Object arg1) {
		this.sendMessage((String) arg1);
	}

	/**
	 * Remet les points d'actions a 0
	 */
	public void resetAP() {
		if (_currentActionPoint < 0)
			_currentActionPoint += _initialAP;
		else
			_currentActionPoint = _initialAP;
	}

	/**
	 * @param actionPoint
	 */
	public void setCurrentActionPoint(int actionPoint) {
		_currentActionPoint = actionPoint;
	}

	/**
	 * @return le nombre de point d'action courant
	 */
	private int getCurrentActionPoint() {
		return _currentActionPoint;
	}

}
